//Debugging and Error Handling
var errorMSG=[];
	errorMSG[01]="La url AJAX no puede estar vacía.";
	errorMSG[02]="Este método no puede ser llamado directamente.";
	errorMSG[03]="Ocurrio un error inesperado en la respuesta a la petición AJAX.";
	errorMSG[04]="Ocurrio un error inesperado en la función ajaxSetData";
var urlRedir=[];
    urlRedir[408]="index.html";		//Time out
    urlRedir[500]="index.html";		//Service Unavailable
    urlRedir[404]="404.html";		//Not Found

//Preload Ajax Loading Image	
jQuery.preLoadImages(IE ? false : true, "/cestavip/css/css_images/ico-loading-32.gif");	

// namespace our code
window.CestaVip = {};

// Class Declaration & Implementation
var CestaVipMain= jQuery.Class.create({
    initialize: function () {
	this.idClass=1;		//Class Identifier (debugging purposes)
	this.debug = IE ? false : true;	//If enabled, it will give output information trough console.log (DOES NOT WORK ON IE)
//	this.debug =false;	//For production	
	this.timeout = 3;	//Timeout in seconds to perform the HTTP petition and retrieve an anwer.
	this.retry=1;		//Retry one time if first attempt failed.
	this.timeoutTimer = "";	//setInterval variable	
	this.loading = false;	//Current Status of the operation.
	this.showLoad = true;	//Loading Image showed/hidden
	this.loadingTarget ="";	//Target of the loading information, to show the image (page/body by default)
	this.ajaxUrl = "";	//URL to make the HTTP request
	this.ajaxReq="";	//Ajax petition variable
	this.ajaxData =  "";	//Response data
        this.ajaxStatus =  "";	//Response status
	this.section="";	//Page section target.
	this.data=[];		//Array of data retriewed, already parsed.
	this.numTargets=0;	//Targets to build the html.
	this.target='';		//Current target that is being modified.
	this.built = '';	//Html built
	this.template='';
        this.tpl = '';		//tpl destination
	this.mode='add';	//push -> Override data, add -> Append data to the end
	this.reloading=false;	//To check if current instance is being reused
	this.cssJson='';
    },
//GETTERS
    getTarget: function () {
        return this.target;
    },
    getBuilt: function () {
        return this.built;
    },
    getAjaxData: function () {
        return this.ajaxData;
    },
    getSection: function (){
	return this.section;
    },
    getAjaxStatus: function () {
        return (this.ajaxStatus == "success");
    },
    getAjaxUrl: function(){
	return this.ajaxUrl;
    },
    getNumTargets: function(){
	return this.numTargets;
    },
    getRetry: function(){
	return this.retry;
    },
    getShowLoad: function(){
	return this.showLoad;
    },
    getLoading: function(){
	return this.loading;
    },
    getLoadingTarget: function(){
	return this.loadingTarget;
    },
    getTimeout: function(){
	return this.timeout;
    },
    getMode: function(){
	return this.mode;
    },
    getReloading: function(){
	return this.reloading;
    },
    getData: function(){
	return this.data;
    },
//SETTERS
    setLoadingTarget: function(value){
	this.loadingTarget=value;
    },
    setLoading: function (value){
    	this.loading=value;
    },
    setReloading: function (value){
    	this.reloading=value;
    },
    setData: function (html, json, target) {
	var nT=this.getNumTargets();
        this.data[nT] = {	//Se añaden los datos al array
		            id: nT,
		            html: html,
		            json: json,
		            target: target
                   };
    },
    setAjaxData: function (data) {
        this.ajaxData=data;
    },
    setAjaxStatus: function (status) {
        this.ajaxStatus =status;
    },
   setCssJson: function (style) {
        this.cssJson = style;
    },
    setTpl: function (tpl) {
        this.tpl = tpl;
    },
    setBuilt: function (built) {
        this.built = built;
    },
    setSection: function (page) {
        if (page === undefined) {
            page = 'generic'; //Si no hay ninguna peculiaridad para ese tpl, desde el buildpage se llamará directamente a this.htmlGenerate();
        }
        this.section = page;
    },
    setAjaxUrl: function (url) {
        if (url != '') {
            this.ajaxUrl = url;
	   
        }
    },
    setShowLoad: function (showLoad) {
        this.showLoad = showLoad;
    },
    setTarget: function (target) {
        this.target = target;
    },
    setAsJsoned: function (target) {
        if (target != "") {
		//console.log("Removing Classtype:"+target+","+this.cssJson);
            $('#'+target).removeClass(this.cssJson);	//Eliminar el estilo cssJson para que no interfiera con futuras llamadas AJAX
           // $(target).addClass(this.cssJson+"ed");
        }
    },
//Otros Métodos sencillos
    incNumTargets: function () { //Incrementar los targets a procesar
        this.numTargets++;
    },  
    decRetry: function(){	//Decrementar los intentos restantes
	this.retry--;
    },
    addBuilt: function (dataJson) {
	//this.built=$.tmpl(this.getTarget(), dataJson);//.appendTo('#'+this.getTarget());
        //this.built += $.tmpl(this.tpl, dataJson);	//Convierte el template html sustituyendo las variables #{} por valores
    },
    resetBuilt: function(){	//Reset de los valores del Tpl y Built (varian por cada target)
	this.setTpl('');
	this.setBuilt('');
    },
    errorMessage:function(errorCode){	//Mostrar mensaje de error en la consola, con breve descripción.

	if (this.debug) console.log('An Error ocurred, errorMessage@'+errorMSG[errorCode]);
    },
    resetData: function(){	//Reset de los valores del Tpl y Built (varian por cada target)
	//console.log("Reseting data.");
	this.data=[];
	this.numTargets=0;
    },
//Precarga de imagenes
    preloadImages: function(data){
        var imgArray= new Array();
	for(img in data){
		if(typeof data[img].img != "undefined"){
			imgArray.push(data[img].img);
		}else break;
	}
	if(imgArray.length >0) jQuery.preLoadImages(this.debug, imgArray);
    },
//Métodos para controlar el timeout
    startTimeout: function () {
	var seconds = this.getTimeout();
	var _root = this;	//IE SCOPE HACK
        if (seconds) {
              this.timeoutTimer = window.setTimeout((function () {	//Iniciamos un timer que si no se detiene llamará a ajaxFail con errornumber=408 (timeout)
		_root.ajaxFail(408);	
            }), seconds * 1000);	//El timer se especifica en milisegundos así que seconds * 1000
        }
    },
    stopTimeout: function () {
	
        if (this.timeout) {
            window.clearTimeout(this.timeoutTimer);	//Eliminamos el timer
            if (this.debug) { console.log("CestaVipMain.stopTimeout(). Timeout Detenido");}
        }
    },
//Método para ocultar la imágen y el div de loading
    stopLoad: function () {
        if (this.getLoading()) {	//Si loading=true
	
            jQuery.stopWaiting(this.getLoadingTarget());	//Ocultamos imagen y div que oscurece la pantalla
            this.setLoading(false);	
            this.setLoadingTarget('');  
        }
    },
//hack para que se muestren las imágenes añadidas por AJAX
    htmlSetExtraImg: function () { 	//La src de las imagenes se pone en el title al generar el template para que funcione en todos los browsers
 	var pathImg="";
	$('#'+this.getSection()+' .' + this.cssJson + '_img').each(function (i) {
		pathImg = $(this).attr("title"); 	//Obtenemos el title
		 if (pathImg != '') {	//Si no está vacio, lo asignamos al src y vaciamos title.
                $(this).attr("src", pathImg);
                $(this).attr("title", '');
            }
	 });
    },
//hack para que se muestren los links añadidos por AJAX 
   htmlSetExtraLinks: function () {	//La url de los links se pone en el title al generar el template para que funcione en todos los browsers
	//console.log("LINKS "+'#'+this.getSection()+'.' + this.cssJson + '_link');        
	$('#'+this.getSection()+' .' + this.cssJson + '_link').each(function () {	//para cada link de este json

            href = $(this).attr("title"); 	//Obtenemos el title
	   //console.log("Link:"+href);
            if (href != '') {		//Si no está vacio, lo asignamos al href y vaciamos title.
                $(this).attr("href", href);
                $(this).attr("title", '');
            }
        });
    },
//Añade en el target actual, el contenido generado (html) que hay en built
    htmlPushAndBuild: function (target, modo, dataJson) {	//add -> Añade al final, push -> sustituye el contenido
	//if (this.debug) console.log("Pushing data:"+target+" Mode->"+modo);//+ "Data:"+data);
	
        if (dataJson != '' && target != '') {
            switch (modo) {
            case 'add':
              $.tmpl(target, dataJson).appendTo('#'+target);
                break;
            case 'push':
            default:
	       $.tmpl(target, dataJson).prependTo('#'+target);	
            }

           
        }
    },
//Para cada target recibido, genera y muestra el html correspondiente
    htmlGenerate: function (options) {
        var html = '';
	if (this.debug) console.log("Generando html, targets a modificar:"+this.numTargets);
        if (this.getNumTargets() > 0) {		//si hay targets..
		var data=this.getData();
		for (a in data) {		//Para cada elemento recibido
		        var target = data[a].target;	//Seleccionamos el elemento
		        var html = data[a].html;		//Seleccionamos el html correspondiente
			var modo = this.getMode(target);
			if(modo=="push" && this.getReloading()) continue;	//Si estamos haciendo push y es una recarga, skip este target
		        if (html) {		//Si no está vacío (Existe)	TODO: is(":empty");
		            this.setTarget(target);	//Asignamos el elemento
			    if (this.debug) console.log("Target Actual:" + target);//+" html:"+html);
			
		            var tpl = $.template(target, html);	//Generamos la plantilla html que se va a modificar con los valores recibidos por ajax.
			  
		            this.setTpl(tpl);			//La asignamos
		            if (jQuery.isArray(data[a].json)) {	//Si es un array de elementos
		                vDataToPush = data[a].json;
		            } else {				//Si es un sólo elemento
		                vDataToPush = [data[a].json];
		            }
			    //Mostrar sólo n elementos?
			    var lim=0;
			    if(this.getShowLimit){	//Si hay limite
					lim= this.getCurrent(target);	//Elemento actual
					if(lim && vDataToPush.length && (this.getShowLimit(target) >= vDataToPush.length )){ //Si llega al final, ejecuta endLimit
						this.endLimit();
					}
			    }
			    //Para cada elemento se genera el Html resultante y se añade a la página.
			    for (var dataElem=lim; dataElem<vDataToPush.length; dataElem++) { 	
				if(typeof options !="undefined") vDataToPush[dataElem] = options.pushData(options.context,vDataToPush[dataElem]);
		            	this.htmlPushAndBuild(target, modo, vDataToPush[dataElem]);	
				if(this.getShowLimit && this.getShowLimit(target)!=0){	//Si hay limite, para ese target, incremento los elementos mostrados
						this.setCurrent(this.getCurrent()+1);
						if(this.getCurrent()>=this.getShowLimit(target)){//Si he llegado al limite, incremento el limite y salgo del bucle
							this.incShowLimit(target);
							break;
						}
						
				}	
			    }
			    	
			    this.setAsJsoned(target);	//Marcar target como "modificado", quitandole el class style especificado
			    if (this.debug) console.log("Target Procesado:" + target);//+" html:"+html);
		        }
		}
        }
	this.setReloading(true);
    },
    htmlInit: function () {	
        if (this.debug) console.log('htmlInit(): Iniciamos el volcado de datos');
        
            try {
	
                this.buildPage(this.getSection());	//Llamamos al método específico de cada clase/bloque
		this.stopLoad();	//Ocultar div e imagen de Loading.
		
		/*
		this.setTooltips(this.getSection());
		this.setExtraInputs();          
		*/

            } catch (e) {
                
                    if (this.debug) console.log(e, 'CestaVipMain.getData.htmlInit.buildPage@' + this.idClass);
               
            }
	 try {
	 	this.htmlSetExtraImg();		//hack para las imágenes añadidas por AJAX
		this.htmlSetExtraLinks();	//hack para los links añadidos por AJAX

		} catch (e) {
                
                    if (this.debug) console.log(e, 'CestaVipMain.getData.htmlInit.htmlSetExtraHacks@' + this.idClass);
               
            }
    },
    ajaxPreInit: function (target) {  
     	
	if (this.getShowLoad()) {	//Sólo si hay que mostrar la imágen de cargando
            if (typeof target=="undefined") {	//Si no hay un target específico, será la pantalla completa (body)
                target = 'body';

            }
            if (this.debug) console.log('ajaxPreInit(): Pre-Inicializando antes de realizar la carga de datos, target:'+target);
	    
	    if (!this.getLoading()) {	//Si Loading=false
		//if (!Prototype.Browser.IE) 	EN IE7+ FUNCIONA
			
			jQuery.startWaiting(target);	//Mostramos el div oscureciendo la pantalla y la imagen de cargando
		        this.setLoadingTarget(target);	//Asignamos el target que se está cargando
		        this.setLoading(true);	    	//Loading=true
	    }
	}
    },
    ajaxFail: function (status) {
	if (this.debug) console.log('CestaVipMain.ajaxFail(): Server Response: ', status );
	this.ajaxReq.abort();	//Abortamos la petición actual
	
	if (this.getRetry() > 0 && status!=404){ //Si hay algún retry posible y el status!=not found, se intenta de nuevo.
		this.decRetry();	//Decrementamos el retry count
		this.ajaxCallData();	//llamada a AJAX
		this.startTimeout();	//Reiniciamos timer
	}else { 
		if (this.debug) console.log('CestaVipMain.ajaxFail(): Unrecoverable error, load stoped.');
		this.stopLoad();	//Ocultar div e imagen Loading.
		//document.location.href = urlRedir[status];
	}
				
    },
    ajaxSet: function (target, json) {
        var html = '';
        if (target != "") {
            	//Comprobación de que el target y el target template existen, sino se mostrara un mensaje de error
		html = $('#'+target+'-template').html();

                if($('#'+target).length==1 && html!=null) {
		    this.setData(html, json, target);	//Se añaden los datos al array
            	    this.incNumTargets();		//Se incrementa el nº de targets a procesar

                } else {

                    if (this.debug) console.log('CestaVipMain.ajaxGetData.ajaxCallData.ajaxResponse.ajaxSet@' + this.idClass + ' Element [' + target + '] or [' + target +'-template] does not exist');    
                
		}
               
        }
    },
    ajaxNoItems: function(target) {
		if($('#'+target)) {		//Comprobamos que existe el target
			notarget = "no_" + target;	//Comprobamos que existe en el html un elemento no_target.
			try {
				if($('#'+notarget).hasClass('hidden')) {	//Si existe el elemento, lo mostramos, quitandole la class hidden
					$('#'+notarget).removeClass('hidden');
				}
				$('#'+target).addClass('hidden');		//Ocultamos el elemento "original" que no tiene datos
			}
			catch(e){
				 if (this.debug) console.log(e, 'CestaVipMain.ajaxGetData.ajaxCallData.ajaxResponse.ajaxNoItems@' + this.idClass + '[' + notarget + ']'); 
			}
		}
	},
     ajaxSetData: function () {
	var data=this.getAjaxData();	//Obtenemos los datos del jSON
	var values;
        if (!jQuery.isArray(data)) {	//Recibimos un objeto con los datos		
           for (var target in data) {  //Para cada item, obtenemos el target y el valor
		values=data[target];
                if (jQuery.isArray(values)) {	//Puede ser un Array de valores
                    this.ajaxSet(target, values);
                    if (values.length == 0) {	//Comprobamos que el Array no estuviera vacío
                        this.ajaxNoItems(target);	//Mostramos texto alternativo
                    } else this.preloadImages(values);	//Iniciamos una precarga de las imagenes, si las hay
                }else {	 		//Puede ser un único elemento
                    this.ajaxSet(target, values);
                    if (!values) {		//Comprobamos que el elemento tuviera algún valor
                        try 
			{   
			    this.ajaxNoItems(target); //Intentamos mostrar texto alternativo

                        } catch (e) {
                                
                            if (this.debug) console.log(e, 'CestaVipMain.ajaxGetData.ajaxCallData.ajaxResponse.ajaxSetData@' + this.idClass + '. No hay items. Intenta mostrar texto alternativo pero no existe ninguno.');
                                
                        }
                        
                    }
                }
            };
        }else this.errorMessage('04');
    },
    ajaxParseResponse: function (response) {
        this.setAjaxData(response.data);	//Los datos por un lado
        this.setAjaxStatus(response.status);	//El estado por otro lado
    },
    ajaxResponse: function (response) {		

	this.stopTimeout();			//Detenemos el timeout
        if (response !== undefined) {		//Si hay respuesta, se analiza.
            this.ajaxParseResponse(response);
        }
        if (this.getAjaxStatus()) {	//status=OK -> JSON recibido y analizado correctamente.
            
	    if(this.debug) console.log('CestaVipMain ajaxGetData(): los datos via AJAX han sido obtenidos.');
   
            try {

                this.ajaxSetData();	//generar array vData a partir de lo recibido

            } catch (e) {
               
                if(this.debug) console.log(e, 'CestaVipMain.ajaxGetData.ajaxCallData.ajaxResponse.ajaxSetData@' + this.idClass);
                
            }
       
            try {

                this.htmlInit();	//Iniciar procedimientos para generar el HTML resultante

            } catch (e) {
                
                if(this.debug) console.log(e, 'CestaVipMain.ajaxGetData.ajaxCallData.ajaxResponse.htmlInit@' + this.idClass);
                
            }
                
       } else {		//status !=OK, algo ha fallado, error
		
                this.stopLoad();    
		this.errorMessage('03');
       } 
       
    },
    ajaxCallData: function () {
        var params;
        if (this.getAjaxUrl() != '') {
            params = "";	//En caso de que la petición se haya completado OK (aún puede haber errores)
    	    var _root=this;	
	    this.ajaxReq = $.getJSON(this.getAjaxUrl(),params,$.context(this).callback('ajaxResponse'))
		.error(function(e) {  
			if(e.status!=0)	{//If NOT ABORTED
			_root.stopTimeout();			//Detenemos el timeout			
			_root.ajaxFail(e.status); 		//Llamamos a ajaxFail por si hay que hacer retry.
			}		
		});
	 
	    //if(this.debug) console.log("Loading ajaxGetData():"+this.getAjaxUrl());		
        } else {
            this.errorMessage('02');
        }
    },
    ajaxGetData: function (urlAjax, section, target) {	//urlAjax es obligatorio
	if(this.getReloading()) {this.htmlInit(); return;}
	if (this.debug) console.log("CestaVipMain getting data from url: "+ urlAjax+" Target section:"+section);
        if (urlAjax != "") {
            this.setSection(section);	//Asignamos sección y target para la imagen de cargando (campos opcionales).
	    this.ajaxPreInit(target);
	    this.setAjaxUrl(urlAjax);	//Asignamos la url.
            this.ajaxCallData();	//Iniciamos los procedimientos para la llamada AJAX.
            this.startTimeout();  	//Iniciamos un timer para el timeout.
        } else {
            this.errorMessage('01');
        }
    }
});
